﻿namespace Atomic.Data.EntityFramework
{
    using System;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Expressions;

    /// <summary>
    /// EF 数据仓库。
    /// </summary>
    /// <typeparam name="TEntityType">实体类型。</typeparam>
    public class EFRepository<TEntityType> : IEFRepository<TEntityType> where TEntityType : class
    {
        /// <summary>
        /// EF 数据上下文。
        /// </summary>
        private readonly IDbContext _context = null;

        /// <summary>
        /// EF 数据访问器。
        /// </summary>
        private IDbSet<TEntityType> _table = null;

        /// <summary>
        /// 初始化 EF 数据仓库。
        /// </summary>
        /// <param name="context">EF 数据上下文。</param>
        public EFRepository(IDbContext context)
        {
            this._context = context;
        }

        /// <summary>
        /// 创建实体。
        /// </summary>
        /// <param name="entity">实体信息。</param>
        public void Create(TEntityType entity)
        {
            this.Table.Add(entity);
        }

        /// <summary>
        /// 更新实体。
        /// </summary>
        /// <param name="entity">实体信息。</param>
        public void Update(TEntityType entity)
        {
            this.Table.Attach(entity);
            _context.Entry(entity).State = EntityState.Modified;
        }

        /// <summary>
        /// 删除实体。
        /// </summary>
        /// <param name="entity">实体信息。</param>
        public void Delete(TEntityType entity)
        {
            this.Table.Remove(entity);
        }

        /// <summary>
        /// 提交。
        /// </summary>
        public void Flush()
        {
            _context.SaveChanges();
        }

        /// <summary>
        /// 根据 id 获得实体。
        /// </summary>
        /// <param name="id">唯一标识。</param>
        /// <returns>实体信息。</returns>
        public TEntityType Get(object id)
        {
            return this.Table.Find(id);
        }

        /// <summary>
        /// 根据表达式条件获得实体。
        /// </summary>
        /// <param name="predicate">表达式条件。</param>
        /// <returns>实体信息。</returns>
        public TEntityType Get(Expression<Func<TEntityType, bool>> predicate)
        {
            return this.Table.FirstOrDefault(predicate);
        }

        /// <summary>
        /// 查询数据。
        /// </summary>
        /// <returns>数据集合。</returns>
        public IQueryable<TEntityType> Query()
        {
            return this.Table;
        }

        /// <summary>
        /// 数据访问器。
        /// </summary>
        protected IDbSet<TEntityType> Table
        {
            get
            {
                if (this._table == null)
                    this._table = _context.Set<TEntityType>();

                return this._table;
            }
        }
    }
}